package com.gaojinqi.base.core.jpa.aspect;

import com.gaojinqi.base.core.jpa.annotation.QueryParam;
import com.gaojinqi.base.core.jpa.util.QueryGroupHelper;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.*;

/**
 * 注解查询切面
 *
 * @author gaojinqi
 * @version 1.0
 * @since 2020年06月23日
 */
@Component
@Aspect
@Slf4j
public class AnnotationQuertAspect {

    @Pointcut(value = "@annotation(com.gaojinqi.base.core.jpa.annotation.Queryable)")
    public void pointcut() {

    }

    @Around("pointcut()")
    public Object around(ProceedingJoinPoint pjp)
            throws Throwable {

        //用的最多通知的签名
        Signature signature = pjp.getSignature();
        MethodSignature msg = (MethodSignature) signature;
        Object target = pjp.getTarget();
        //获取注解标注的方法
        Method method = target.getClass().getMethod(msg.getName(), msg.getParameterTypes());
        // 获取方法参数
        Object[] args = pjp.getArgs();
        // 要清除的入参对象
        Set<Object> clearArgs = new LinkedHashSet<>();
        Annotation[][] parameterAnnotations = method.getParameterAnnotations();
        for (int i = 0; i < parameterAnnotations.length; i++) {
            Annotation[] parameterAnnotation = parameterAnnotations[i];
            for (Annotation annotation : parameterAnnotation) {
                Object arg = args[i];
                // 设置分组，不覆盖以前的值
                if (annotation.annotationType().equals(QueryParam.class)
                        && !QueryGroupHelper.hasBean(arg)) {
                    QueryParam queryParam = (QueryParam) annotation;
                    clearArgs.add(arg);
                    QueryGroupHelper.setGroups(arg, queryParam.groups());
                }
            }
        }
        // 执行方法
        Object result;
        try {
            result = pjp.proceed(args);
        } finally {
            if (!clearArgs.isEmpty()) {
                for (Object arg : clearArgs) {
                    QueryGroupHelper.clearGroups(arg);
                }

            }
        }
        return result;
    }

}
